#include <iostream>
#include <fstream>
#include <sstream>
#include <windows.h>

using namespace std;
const string lineTxt = " - c++/go/cangjie 测试文本写入文件的速度/性能，需要高频写入日志的场景对写文件性能关注会比较高 - 2024 ++++ c++/go/cangjie 测试文本写入文件的速度/性能，需要高频写入日志的场景对写文件性能关注会比较高 - 2024";

//  文本写入文件
streamsize stringWriteToFile();
streamsize stringWriteToFile2();


int main() {
    DWORD startSec = GetTickCount();
    streamsize totalWriteSize = 0;
    for (int i = 0; i < 10; i++) {
        totalWriteSize = stringWriteToFile2();
    }

    DWORD useMillionSecond = (GetTickCount() - startSec) / 10;
    cout << "文件写入完毕,文件总大小：" << totalWriteSize << " ，平均单次耗时(ms):" << useMillionSecond << endl;
    return 0;
}

//  文本写入文件（使用 ostringstream 对象的缓冲区功能）
streamsize stringWriteToFile() {
    wstring filePath = L"D:/写文件/log_cpp_with_buffer.txt";
    int rows = 1000000;      // 写入100万行文本，模拟写入日志场景
    fstream fs(filePath.c_str(), ios::out | ios::trunc | ios::binary);
    if (!fs) {
        cerr << "创建文件出错" << endl;
        return 0;
    } else {
        ostringstream bufferStream;
        for (int i = 1; i <= rows; i++) {
         // 先将数据写入  fstream 自带的缓冲区
          //  fs << to_string(i) + lineTxt + "\n";
            bufferStream<< to_string(i) + lineTxt + "\n";
            if (i % 10000 == 0) {
                fs.write(bufferStream.str().c_str(),bufferStream.str().length());
                bufferStream.str("");
            }
        }

        fs.seekg(0, ios::end);
        streamsize totalWriteSize = fs.tellg();
        fs.close();
        return totalWriteSize;
    }
}

//  文本写入文件（模拟缓冲区）
streamsize stringWriteToFile2() {
    wstring filePath = L"D:/写文件/log_cpp_with_buffer.txt";
    int rows = 1000000;      // 写入100万行文本，模拟写入日志场景
    fstream fs(filePath.c_str(), ios::out | ios::trunc | ios::binary);
    if (!fs) {
        cerr << "创建文件出错" << endl;
        return 0;
    } else {
        string tmpStr = "";
        for (int i = 1; i <= rows; i++) {
            //  将输入写入模拟的缓冲区
            tmpStr += to_string(i) + lineTxt + "\n";
            //fs << to_string(i) + lineTxt + "\n";  //  fstream 自带的缓冲区测试发现性能不高，我们使用 string临时存储、每隔1万次循环，写入文件一次
            if (i % 10000 == 0) {
                //  fs.flush();//  每隔 1 万 行将数据刷新到SSD硬盘
                fs.write(tmpStr.c_str(), tmpStr.length());
                tmpStr = "";
            }
        }

        fs.seekg(0, ios::end);
        streamsize totalWriteSize = fs.tellg();
        fs.close();
        return totalWriteSize;
    }
}